#include <stdio.h>

#if defined(_WIN32) || defined(_WIN64)
	#include <Windows.h>
#else
	#include <unistd.h>
#endif

#include "globals.h"
#include "Logic.h"
#include "Parser.h"
#include "Viewer.h"
#include "Menu.h"

#define AGORA_TEST true

agr_user user = {0};
Logic *logic = NULL;
Parser *parser = NULL;
Viewer *viewer = NULL;

int cleanup(){
	if(logic)
	{
		delete logic;
	}
	if(parser)
	{
		delete parser;
	}
	if(viewer)
	{
		delete viewer;
	}

	return 0;
}

int main()
{
	// --------------------------------- //
	// ----- INITIALIZE MAIN LOGIC ----- //
	// --------------------------------- //
	viewer = new Viewer();
	logic = Logic::initializeLogic(&user);
	parser = Parser::initializeNet(&user, logic);

	#if defined(AGORA_TEST)
		if(parser == NULL){
			parser = new Parser(&user, logic);
		}

		// -------------------------------- //
		// ----- CREATE TEST FILE 5KB ----- //
		// -------------------------------- //

		agr_file *file = logic->createFile("C:\\Agora\\test.log");
		viewer->print("Inflate: %d\n", (int)logic->fileInflate(file, 200*1024*1024)); //200 MB
		viewer->print("Read File Chunks: %d\n", (int)logic->readFileChunks(file));

	#else
		bool error = false;
		if(logic == NULL)
		{
			viewer->print("Error initializing logic\n");
		}
		if(parser == NULL)
		{
			viewer->print("Error initializing network\n");
		}

		if(!logic || !parser)
		{
			return cleanup();
		}
	#endif

	logic->detectFiles();

	#if defined(AGORA_TEST)
		// ----------------------------------- //
		// ----- START DOWNLOADING FILES ----- //
		// ----------------------------------- //

		//Connect to a NOTEST version
		agr_user u; memset(&u, 0, sizeof(agr_user));
		u.ip.b1 = 127;
		u.ip.b4 = 1;

		Parser::initializeConnection(&u, logic);		

		#if defined(_WIN32) || defined(_WIN64)
			Sleep(1000);
		#else
			sleep(1000);
		#endif
	#endif

#if defined(VIEWER_CONSOLE_MODE)
	Menu <Parser, bool, u64> *m = new Menu<Parser, bool, u64>(parser, viewer, false);

	std::map<int, char*> opts;
	opts.insert(std::pair<int, char*>(1, "Show user list"));
	opts.insert(std::pair<int, char*>(2, "Retrieve user files"));
	opts.insert(std::pair<int, char*>(3, "Retrieve file"));
	opts.insert(std::pair<int, char*>(4, "Exit"));
	m->setOptions(opts);

	m->setCallbacks(2, &Parser::requestUserID, 0);

	while(parser->getStatus() != STATUS_DISCONNECTED)
	{
		viewer->displayMainMenu<Parser, bool, u64>(m);
		#if defined(_WIN32) || defined(_WIN64)
			Sleep(1000);
		#else
			sleep(1000);
		#endif
	}
#elif defined(VIEWER_GUI_MODE)
	//throw new Exception("Viewer GUI mode not implemented!!");
#else
	//throw new Exception("Viewer not implemented!!");
#endif

	return cleanup();
}
